package org.goyo.main.services.log;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.goyo.common.baseBean.Constants;
import org.goyo.common.exception.DBException;
import org.goyo.common.exception.ServiceException;
import org.goyo.common.utils.JSONUtil;
import org.goyo.main.domain.entity.system.SysLog;
import org.goyo.main.domain.entity.system.SysUser;
import org.goyo.main.services.system.ISystemService;
import org.goyo.main.web.controller.system.SessionUtil;
import org.goyo.main.web.controller.system.SystemController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;


@Aspect
public class LogService {
  
  private static Logger logger = LoggerFactory.getLogger(LogService.class);
  @Autowired
  private ISystemService systemService;
  

  public void setSystemService(ISystemService systemService) {
    this.systemService = systemService;
  }

  public LogService() {
    // System.out.println("Aop");
  }
  
/*  @Before("execution(* org.goyo.main.web..*.*(..))")
  public void logAll(JoinPoint jp) throws Throwable {
    HttpServletRequest request =
        ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    
    SysLog slog = new SysLog();
    
    slog.setCreateTime(new Date());
    slog.setIp(getIpAddress(request));
    slog.setLogType(Constants.LOG_TYPE_OPERATION);
    slog.setMethodsNote(getMthodRemark(jp));
    slog.setParameter(JSONUtil.obj2Json(request.getParameterMap()));
    slog.setUrl( request.getServletPath());
    SecurityContextImpl securityContextImpl = (SecurityContextImpl) request
        .getSession().getAttribute("SPRING_SECURITY_CONTEXT");
    SysUser user = (SysUser)SessionUtil.getAttribute("user");
    if (null != user) {
      slog.setUserName(user.getUserName());
      slog.setUserId(user.getUuid());
    }
    
    
    String className = jp.getThis().toString();
    String methodName = jp.getSignature().getName();   //获得方法名
    
    System. out.println("=====================================" );
    System. out.println("====位于：" +className);
    System. out.println("====调用" +methodName+"方法-开始！");
    System.out.println("=====方法备注："+getMthodRemark(jp));
    Object[] args = jp.getArgs();  //获得参数列表
     if(args.length <=0){
          System. out.println("====" +methodName+"方法没有参数");
    } else{
           for(int i=0; i<args.length; i++){
             if(args[i] instanceof HttpServletRequest) {
               HttpServletRequest re = (HttpServletRequest) args[i];
               System.out.println(JSONObject.fromObject(re.getParameterMap()));
             }else if(args[i] instanceof HttpServletResponse){
               HttpServletResponse rep = (HttpServletResponse) args[i];
             }
          System. out.println("====参数  " +(i+1)+"："+args[i]);
      }
    }
    System. out.println("=====================================" );
  }*/

  @After("execution(* org.goyo.main.web..*.*(..))")
  public void after(JoinPoint jp) throws Throwable {
    HttpServletRequest request =
        ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    
    SysLog slog = new SysLog();
    
    slog.setCreateTime(new Date());
    slog.setIp(getIpAddress(request));
    slog.setLogType(Constants.LOG_TYPE_OPERATION);
    slog.setMethodsNote(getMthodRemark(jp));
    slog.setParameter(JSONUtil.obj2Json(request.getParameterMap()));
    slog.setUrl( request.getServletPath());
    /*SecurityContextImpl securityContextImpl = (SecurityContextImpl) request
        .getSession().getAttribute("SPRING_SECURITY_CONTEXT");*/
    SysUser user = (SysUser)SessionUtil.getAttribute("user");
    if (null != user) {
      slog.setUserName(user.getUserName());
      slog.setUserId(user.getUuid());
    }
    systemService.saveLog(slog);
    
    /*
    HttpServletRequest request =
        ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    System.out.println("===IP: "+getIpAddress(request));
    SecurityContextImpl securityContextImpl = (SecurityContextImpl) request
        .getSession().getAttribute("SPRING_SECURITY_CONTEXT");
    if(null!=securityContextImpl&&null!=securityContextImpl.getAuthentication()){
   // 登录名
      System.out.println("Username:"
       + securityContextImpl.getAuthentication().getName());
      // 登录密码，未加密的
      System.out.println("Credentials:"
       + securityContextImpl.getAuthentication().getCredentials());
      WebAuthenticationDetails details = (WebAuthenticationDetails) securityContextImpl
       .getAuthentication().getDetails();
      // 获得访问地址
      System.out.println("RemoteAddress" + details.getRemoteAddress());
      // 获得sessionid
      System.out.println("SessionId" + details.getSessionId());
      // 获得当前用户所拥有的权限
      List<GrantedAuthority> authorities = (List<GrantedAuthority>) securityContextImpl
       .getAuthentication().getAuthorities();
      for (GrantedAuthority grantedAuthority : authorities) {
       System.out.println("Authority" + grantedAuthority.getAuthority());
      }
    }*/
  }

  // 方法执行的前后调用
/*  @Around("execution(* org.goyo.main.web.controller.system.*.*(..))")
  public Object around(ProceedingJoinPoint point) throws Throwable {
    HttpServletRequest request =
        ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");
    Calendar ca = Calendar.getInstance();
    String operDate = df.format(ca.getTime());
    String ip = getIpAddress(request);
    // ShiroUser user = (ShiroUser) SecurityUtils.getSubject().getPrincipal();
    
     * String loginName; String name; if (user != null) { loginName = user.loginName; name =
     * user.name; } else { loginName = "anonymousUser"; name = "匿名用户"; }
     

    String monthRemark = getMthodRemark(point);
    String monthName = point.getSignature().getName();
    String packages = point.getThis().getClass().getName();
    if (packages.indexOf("$$EnhancerByCGLIB$$") > -1) { // 如果是CGLIB动态生成的类
      try {
        packages = packages.substring(0, packages.indexOf("$$"));
      } catch (Exception ex) {
        ex.printStackTrace();
      }
    }
    Object object;
    try {
      object = point.proceed();
    } catch (Exception e) {
      // 异常处理记录日志..log.error(e);
      throw e;
    }
    
     * SysLog sysLog = new SysLog(); sysLog.setIpAddress(ip); sysLog.setLoginName(loginName);
     * sysLog.setName(name); sysLog.setMonthName(packages + "." + monthName);
     * sysLog.setMonthRemark(monthRemark); sysLog.setOperDate(operDate); entityService.save(sysLog);
     
    return object;
  }*/

  // 方法运行出现异常时调用
  @AfterThrowing(pointcut = "execution(* org.goyo.main.web..*.*(..))", throwing = "ex")
  public void afterThrowing(Exception ex) {
    logger.error(ex.getMessage(),ex);
    HttpServletRequest request =
        ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    SysLog slog = new SysLog();
    slog.setErrorMsg(ex.getMessage()+ex.toString());
    slog.setCreateTime(new Date());
   
    slog.setIp(getIpAddress(request));
    slog.setLogType(Constants.LOG_TYPE_ERROR);
    slog.setParameter(JSONUtil.obj2Json(request.getParameterMap()));
    slog.setUrl( request.getServletPath());
    /*SecurityContextImpl securityContextImpl = (SecurityContextImpl) request
        .getSession().getAttribute("SPRING_SECURITY_CONTEXT");*/
    SysUser user = (SysUser)SessionUtil.getAttribute("user");
    if (null != user) {
      slog.setUserName(user.getUserName());
      slog.setUserId(user.getUuid());
    }
    try {
      slog.setMethodsNote(getMthodRemark(ex));
      systemService.saveLog(slog);
    } catch (Exception e) {
      logger.error(e.getMessage(),e);
    }
  }

  
  // 获取方法的中文备注____根据堆栈信息
  public static String getMthodRemark(Exception ex) throws Exception {
    String targetName = ex.getStackTrace()[0].getClass().getName();
    String methodName = ex.getStackTrace()[0].getMethodName();

    Class targetClass = Class.forName(targetName);
    Method[] method = targetClass.getMethods();
    String methode = "";
    for (Method m : method) {
      if (m.getName().equals(methodName)) {
           MethodLog methodCache = m.getAnnotation(MethodLog.class); 
           if (methodCache != null) {
             methode = methodCache.value(); 
           }
           break;
      }
    }
    return methode;
  }
  
  // 获取方法的中文备注____用于记录用户的操作日志描述
  public static String getMthodRemark(JoinPoint joinPoint) throws Exception {
    String targetName = joinPoint.getTarget().getClass().getName();
    String methodName = joinPoint.getSignature().getName();
    Object[] arguments = joinPoint.getArgs();

    Class targetClass = Class.forName(targetName);
    Method[] method = targetClass.getMethods();
    String methode = "";
    for (Method m : method) {
      if (m.getName().equals(methodName)) {
        Class[] tmpCs = m.getParameterTypes();
        if (tmpCs.length == arguments.length) {
           MethodLog methodCache = m.getAnnotation(MethodLog.class); 
           if (methodCache != null) {
           methode = methodCache.value(); 
        }
          break;
        }
      }
    }
    return methode;
  }

  public String getIpAddress(HttpServletRequest request) {
    String ip = request.getHeader("x-forwarded-for");
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getHeader("Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getHeader("WL-Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getRemoteAddr();
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getHeader("http_client_ip");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getHeader("HTTP_X_FORWARDED_FOR");
    }
    if (ip != null && ip.indexOf(",") != -1) {
      ip = ip.substring(ip.lastIndexOf(",") + 1, ip.length()).trim();
    }
    if ("0:0:0:0:0:0:0:1".equals(ip)) {
      ip = "127.0.0.1";
    }
    return ip;
  }
}
